package com.thoughtworks.android.androsphere.service.auth;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import com.thoughtworks.android.androsphere.service.GoogleServiceConstants;
import com.thoughtworks.util.http.HttpResponseHandler;
import com.thoughtworks.util.http.HttpTemplate;

public class ClientLoginAuthTokenGenerator {
    private static final Logger logger = Logger.getLogger(ClientLoginAuthTokenGenerator.class);

    private ClientLoginAuthParams requestParams;
    private HttpTemplate httpTemplate;

    public ClientLoginAuthTokenGenerator(ClientLoginAuthParams requestParams, HttpTemplate httpTemplate) {
        this.requestParams = requestParams;
        this.httpTemplate = httpTemplate;
    }

    public String generate() {
        ClientLoginAuthResponseHandler handler = new ClientLoginAuthResponseHandler();

        logger.debug("Sending ClientLogin auth request..");
        httpTemplate.execute(createPostData(), handler);

        return handler.getAuthToken();
    }

    private Map<String, String> createPostData() {
        Map<String, String> postData = new HashMap<String, String>();

        postData.put(GoogleServiceConstants.CLIENT_LOGIN_AUTH_PARAM_EMAIL, requestParams.getEmail());
        postData.put(GoogleServiceConstants.CLIENT_LOGIN_AUTH_PARAM_PASS, requestParams.getPassword());
        postData.put(GoogleServiceConstants.CLIENT_LOGIN_AUTH_PARAM_ACCOUNT_TYPE, requestParams.getAccountType());
        postData.put(GoogleServiceConstants.CLIENT_LOGIN_AUTH_PARAM_SOURCE, requestParams.getSource());
        postData.put(GoogleServiceConstants.CLIENT_LOGIN_AUTH_PARAM_SERVICE, requestParams.getServiceName());

        return postData;
    }

    private class ClientLoginAuthResponseHandler implements HttpResponseHandler {
        private static final String AUTH = "Auth";
        private String token;

        public void handle(int responseCode, Map<String, String> headers, InputStream responseStream) {
            if (responseCode == 200) {
                logger.debug("Received 200 response for ClientLogin Auth");

                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(responseStream));
                String line;
                try {
                    while ((line = bufferedReader.readLine()) != null) {
                        logger.debug(line);

                        if (line.contains(AUTH)) {
                            token = line.substring(5);
                            return;
                        }
                    }
                } catch (IOException e) {
                    logger.error("Error reading ClientLogin response", e);
                }
            } else {
                logger.error("ClientLogin Auth failed, code : " + responseCode);
            }
        }

        public String getAuthToken() {
            return token;
        }
    }
}
